﻿using BPM.Web.Shared.Extensions;
using Microsoft.AspNetCore.Components.Authorization;

namespace BPM.Web.Shared;

/// <summary>
/// 账票状态上下文
/// </summary>
public class TokenContext
{
    //private Semaphore _semaphore;

    public TokenContext(ITokenInterceptor interceptor)
    {
        Interceptor = interceptor;
        //_semaphore = new Semaphore(1, 1);
    }

    /// <summary>
    /// 当前Token的拦截器
    /// </summary>
    public ITokenInterceptor Interceptor { get; set; }

    /// <summary>
    /// 授权账票
    /// </summary>
    public string? AccessToken { get; private set; }

    /// <summary>
    /// 刷新账票
    /// </summary>
    public string? RefreshToken { get; private set; }

    /// <summary>
    /// 指示授权账票过期时间
    /// </summary>
    public long AccessExpir { get; private set; }

    /// <summary>
    /// 指示授权账票过期时间
    /// </summary>
    public long RefreshExpir { get; private set; }

    /// <summary>
    /// 指示Token临近过期或已经过期（提前60秒）
    /// </summary>
    public bool IsExpiringSoon
    {
        get
        {
            var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            return AccessExpir - now < 60 || RefreshExpir - now < 60;
        }
    }

    /// <summary>
    /// 获得/设置 是否已授权
    /// </summary>
    public bool IsAuthenticated { get; private set; }

    /// <summary>
    /// 获得/设置 是否需要刷新客户端本地Token
    /// </summary>
    public bool NeedRefreshClientToken { get; private set; }

    /// <summary>
    /// 刷新客户端会话Token事件
    /// </summary>
    public event EventHandler<bool>? RefreshClientToken;

    /// <summary>
    /// 更新客户端LocalStorage的Token事件
    /// </summary>
    public event EventHandler<(string?, string?)>? UpdateClientToken;

    /// <summary>
    /// 读取Token信息
    /// </summary>
    /// <param name="state"></param>
    public void LoadToken(AuthenticationState? state)
    {
        if (state?.User.Identity?.IsAuthenticated == true)
        {
            IsAuthenticated = true;
            AccessToken = state.User.FindFirst(x => x.Type == "AccessToken")?.Value;
            AccessExpir = TokenExtensions.GerTokenExpir(state.User.Claims, "AccessExpir");
            RefreshToken = state.User.FindFirst(x => x.Type == "RefreshToken")?.Value;
            RefreshExpir = TokenExtensions.GerTokenExpir(state.User.Claims, "RefreshExpir");
        }
    }

    /// <summary>
    /// 更新Token信息
    /// </summary>
    /// <param name="isAuthenticated"></param>
    /// <param name="accessToken"></param>
    /// <param name="refreshToken"></param>
    public void UpdateToken(bool isAuthenticated, string? accessToken, string? refreshToken)
    {
        if (AccessToken == accessToken && RefreshToken == refreshToken)
        {
            return;
        }

        IsAuthenticated = isAuthenticated;
        AccessToken = accessToken;
        AccessExpir = TokenExtensions.GerTokenExpir(AccessToken, "exp");
        RefreshToken = refreshToken;
        RefreshExpir = TokenExtensions.GerTokenExpir(RefreshToken, "exp");

        //标记状态，写入到客户端LocalStorage
        NeedRefreshClientToken = true;
        RefreshClientToken?.Invoke(null, IsAuthenticated);
    }

    /// <summary>
    /// 客户端LocalStorage的Token更新处理回调方法
    /// </summary>
    public void UpdateClientTokenCallback()
    {
        //_semaphore.WaitOne();
        if (NeedRefreshClientToken)
        {
            NeedRefreshClientToken = false;
            UpdateClientToken?.Invoke(null, (AccessToken, RefreshToken));
        }
        //_semaphore.Release();
    }
}

